function y = WiSiL_Rx_llrComp(vector_x, nbpsc, eq_sigma2, modulation, frame)
% WISIL_RX_LLRCOMP Computes log-likelihood ratios (LLRs) for OFDM
%
%   Y = LLRCOMP( X, NBPSC, SIGMAW2, MODULATIO, FRAME )computes LLRs Y based
%   on channel outputs X, given the number of bits per subcarrier NBPSC and
%   the the noise variances  SIGMAW2 at each subcarrier after equalization.
%   The input signal X is assumed to be normalized. 
%   NBPSC must be an integer belonging to {1,2,4,6}.
%   X must be an M x N matrix. M subcarriers, N OFDM symbols.
%   Y has dimension M*NBPSC x N.
%   MODULATION is a struct containing the modulation parameters and FRAME
%   is a struct containing the frame parameters.
 
% History:
% Andre Noll Barreto  25.07.2001
%   created

%include parameters
wordSize = log2(modulation.M);
numCarr = frame.numCarr;
N_DL_Symb = frame.N_DL_Symb;

%turn vector_x into a matrix of dimensions [numCarr-1, numSymbols]
x = reshape(vector_x, numCarr-1, N_DL_Symb*frame.slot);
X = (numCarr-1)*wordSize; %number of bits in one ofdm symbol

sigmaw2r = 1./ eq_sigma2;

switch nbpsc
    case 1
        y = real(x) .* sigmaw2r;
        y = reshape(y, numel(y),1);
    case 2
        x = x * sqrt(2);
        x = x .* sigmaw2r;
        y(1:2:(X-1),:) = real(x);
        y(2:2:X,:) = imag(x);
    case 4
        x = x * sqrt(10);
        y(1:4:(X-3),:) = f_type2(real(x),0) .* sigmaw2r;
        y(2:4:(X-2),:) = f_type2(imag(x),0) .* sigmaw2r;
        y(3:4:(X-1),:) = f_type2(real(x),1) .* sigmaw2r;
        y(4:4:X,:) = f_type2(imag(x),1) .* sigmaw2r;
    case 6
        x = x * sqrt(42);
        y(1:6:(X-5),:) = f_type3(real(x),0) .* sigmaw2r;
        y(2:6:(X-4),:) = f_type3(imag(x),0) .* sigmaw2r;
        y(3:6:(X-3),:) = f_type3(real(x),1) .* sigmaw2r;
        y(4:6:(X-2),:) = f_type3(imag(x),1) .* sigmaw2r;
        y(5:6:(X-1),:) = f_type3(real(x),2) .* sigmaw2r;
        y(6:6:X,:) = f_type3(imag(x),2) .* sigmaw2r;

    otherwise
        error ('LLRCOMP: invalid NBPSC');
end
 
 
function f = f_type2(x,n)
    if n == 0
        f = x + (abs(x)>2) .* (x-2*sign(x));
    else
        f = 2 - abs(x);
    end
    
 
function f = f_type3(x,n)
    xAbs = abs(x);
    switch n
    case 0
        aux = min(floor(xAbs/2),3);
        f = (aux+1).*(xAbs-aux);
        f = f.*sign(x);
    case 1
        f = (xAbs>6).*(2*(5-xAbs)) + (xAbs>2 & xAbs<=6).*(4-xAbs) + (xAbs<=2).*(2*(3-xAbs));
    case 2
        f = 2 - abs(4-xAbs);
    end